#ifndef LOG_H_
#define LOG_H_

#include <syslog.h>
#include <errno.h>

#ifndef NDEBUG

# include <stdio.h>
# include <sys/time.h>

# define FXS_LOG_OPTION                     LOG_CONS
# define FXS_LOG_MASK                       LOG_UPTO(LOG_DEBUG)

# define LOG(level, fmt, args...) \
    do { \
        int se = errno; \
        struct timeval tv; \
        struct timezone tz; \
        gettimeofday(&tv, &tz); \
        tv.tv_sec -= tz.tz_minuteswest * 60; \
        int s = tv.tv_sec % 60; \
        int m = tv.tv_sec / 60 % 60; \
        int h = tv.tv_sec / 3600 % 24; \
        unsigned long msec = tv.tv_usec; \
        syslog(level, "%02d:%02d:%02d.%06lu: %s:%d: " fmt "\n", h, m, s, msec, __FILE__, __LINE__, ## args); \
        errno = se; \
    } while (0)

# define LOG_DATA(datap, datalen, fmt, args...) \
    do { \
        int se = errno; \
        char __str__[(datalen) * 3 + 1]; \
        __str__[0] = '\0'; \
        const void *__dptr__; \
        size_t __i__, __n__; \
        for (__dptr__ = (datap), __i__ = 0; __i__ < (size_t)(datalen); ++__i__) { \
            __n__ = 3 * __i__; \
            snprintf(__str__ + __n__, sizeof(__str__) - __n__, "%02hhX ", *(unsigned char *) __dptr__++); \
        } \
        LOGD(fmt ": %s", ## args, __str__); \
        errno = se; \
    } while (0)

#else

# define FXS_LOG_OPTION                     LOG_CONS
# define FXS_LOG_MASK                       LOG_UPTO(LOG_INFO)

# define LOG(level, fmt, args...) \
    do { \
        int se = errno; \
        syslog(level, fmt, ## args); \
        errno = se; \
    } while (0)

# define LOG_DATA(datap, datalen, fmt, args...)

#endif

#define OPENLOG(ident, option, facility)    openlog(ident, option, facility)
#define SETLOGMASK(mask)                    setlogmask(mask)

#define LOGC(fmt, args...)                  LOG(LOG_CRIT, fmt, ## args)
#define LOGE(fmt, args...)                  LOG(LOG_ERR, fmt, ## args)
#define LOGW(fmt, args...)                  LOG(LOG_WARNING, fmt, ## args)
#define LOGN(fmt, args...)                  LOG(LOG_NOTICE, fmt, ## args)
#define LOGI(fmt, args...)                  LOG(LOG_INFO, fmt, ## args)
#define LOGD(fmt, args...)                  LOG(LOG_DEBUG, fmt, ## args)

#endif /* LOG_H_ */
